package tetris.agent;

import java.util.*;
import java.lang.Object;

import org.apache.commons.math3.distribution.AbstractMultivariateRealDistribution;
import org.apache.commons.math3.distribution.MultivariateNormalDistribution;

public class multiVariateGaussian {

	public MultivariateNormalDistribution fitToSamples(double[][] samples){

		int numSamples = samples.length;
		double[] meanVec = new double[12];
		double[][] covMat = new double[12][12];

		// Get mean from samples
		double[] sumMean = new double[12];
		for(int i=0; i<numSamples;i++){
			sumMean = scalarProduct(sumArrays(sumMean, samples[i], true), samples.length, false);
		}	
		meanVec = sumMean;

		// Get covariance from samples
		double[][] mulCov = new double[12][12];
		for(int i=0; i<numSamples;i++){
			double[] x_Mu = sumArrays(samples[i], meanVec, false);
			mulCov = mulArrays(x_Mu, x_Mu);
		}	
		covMat = mulCov;


		MultivariateNormalDistribution obj = new MultivariateNormalDistribution( meanVec, covMat);
		return obj;
		
	}
	
	
	
	// Utility functions
	public static double[] scalarProduct(double[] Matrix, double K,boolean operator){
		double KPrd[] =  new double[Matrix.length];

		// operator = true does scalar product else scalar division
		if (operator==true){
			for (int i = 0; i < Matrix.length; i++) {
				KPrd[i] = K * Matrix[i];
			}
		}
		else{
			for (int i = 0; i < Matrix.length; i++) {
				KPrd[i] = Matrix[i]/K;
			}
		}
		return KPrd;
	}

	public static double[] sumArrays(double[] Matrix1, double[] Matrix2, boolean operator){
		double[] sumArr = new double[Matrix1.length];

		// operator = true does addition else subtraction
		if (operator==true){
			for (int i = 0; i < Matrix1.length; i++) {
				sumArr[i]=  Matrix1[i] + Matrix2[i];
			}
		}
		else{
			for (int i = 0; i < Matrix1.length; i++) {
				sumArr[i]=  Matrix1[i] - Matrix2[i];
			}
		}
		return sumArr;
	}

	public static double[][] mulArrays(double[] Matrix1, double[] Matrix2){
		double c[][] = new double[12][12];

		for(int i=0;i<Matrix1.length;i++){
			for(int j=0;j<Matrix2.length;j++){
				c[i][j]= c[i][j] +(Matrix1[i] * Matrix2[j])/12.0;

			}
		}

		return c;
	}
	
	public static double dotProduct(double[] fts, double[] wt){
		double dtPrd = 0.0;
		for (int i = 0; i < wt.length; i++) {
			dtPrd += fts[i] * wt[i];
		}
		return dtPrd;
	}

}